package com.cory.admin.sys.core.privilege.aspect;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.cory.admin.sys.config.AdminConstants;
import com.cory.admin.sys.core.privilege.annotation.HasAnyPermission;
import com.cory.admin.sys.core.privilege.annotation.HasPermission;
import com.cory.boot.domain.CustomRuntimeException;


/**
 * @author xiongcong
 * @date 2022-05-06
 */
@Aspect
@Component
public class PrivilegeAspect {

    @Pointcut("@annotation(com.cory.admin.sys.core.privilege.annotation.HasPermission) || @annotation(com.cory.admin.sys.core.privilege.annotation.HasAnyPermission)")
    public void privilegeAspect(){}
    
    @SuppressWarnings({"unchecked"})
    @Before("privilegeAspect()")
    public void around(JoinPoint pjp) throws Throwable {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        
        MethodSignature methodSignature =  (MethodSignature) pjp.getSignature();
        Method method = methodSignature.getMethod();
        
        Annotation[] annos = method.getAnnotations();
        
        Arrays.asList(annos).forEach(a -> {
            if (a instanceof HasPermission) {
                List<String> userPermissions = (List<String>)request.getSession().getAttribute(AdminConstants.SESSION_USER_PERMISSION);
                if (!userPermissions.contains(((HasPermission) a).permission())) {
                    throw new CustomRuntimeException("无访问权限");
                }
            }
            
            if (a instanceof HasAnyPermission) {
                List<String> userPermissions = (List<String>)request.getSession().getAttribute(AdminConstants.SESSION_USER_PERMISSION);
                String[] permissions = ((HasAnyPermission) a).permissions();
                if (!Stream.of(permissions).anyMatch(userPermissions::contains)) {
                    throw new CustomRuntimeException("无访问权限");
                }
            }
        });
        
    }
}
